package com.quick.api.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.quick.api.dblog.DynamicDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author ：chicunxiang
 * @date ：Created in 2021/3/25 13:50
 * @description：
 * @version: 1.0
 */
@Configuration
public class DataSourceConfig {

    @Value("${mybatis.mapper-locations}")
    private String mapperLocation;

    @Autowired
    private DataSourceConfiguration mSourceConfiguration;

    @Autowired
    private DataSourceProperties mDataSourceProperties;

    private DataSource dataSourceCreate(DataSourceConfiguration.DataSourceConfigProxy dataSourceConfigProxy) {
        DruidDataSource druidDataSourceSalve = new DruidDataSource();
        druidDataSourceSalve.setUrl(dataSourceConfigProxy.getUrl());
        druidDataSourceSalve.setUsername(dataSourceConfigProxy.getUsername());
        druidDataSourceSalve.setPassword(dataSourceConfigProxy.getPassword());
        druidDataSourceSalve.setDriverClassName(dataSourceConfigProxy.getDriverClassName());
        return druidDataSourceSalve;
    }

    private DataSource dataSourceCreateFromDefault() {
        DruidDataSource druidDataSourceSalve = new DruidDataSource();
        druidDataSourceSalve.setUrl(mDataSourceProperties.getUrl());
        druidDataSourceSalve.setUsername(mDataSourceProperties.getUsername());
        druidDataSourceSalve.setPassword(mDataSourceProperties.getPassword());
        druidDataSourceSalve.setDriverClassName(mDataSourceProperties.getDriverClassName());
        return druidDataSourceSalve;
    }

    private DynamicDataSource doDefaultDynamicDataSource() {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        // 获取默认的数据源
        DataSource dataSource = dataSourceCreateFromDefault();
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put("master", dataSource);
        DynamicDataSourceContextHolder.DEFAULT_DATA_SOURCE = "master";
        DynamicDataSourceContextHolder.DATA_SOURCE_IS_ONE = true;
        DynamicDataSourceContextHolder.setDefaultDataSource();
        dynamicDataSource.setDefaultTargetDataSource(dataSource); // 默认使用主库源
        dynamicDataSource.setTargetDataSources(targetDataSources);
        return dynamicDataSource;
    }


    /**
     * 动态数据源，配置需要使用到的多个数据源
     *
     * @return
     */
    @Bean
    public DynamicDataSource dynamicDataSource() {
        if (!DataSourceConstant.ENABLE_DBS) {
            return doDefaultDynamicDataSource();
        }
        List<DataSourceConfiguration.DataSourceConfigProxy> datasource = mSourceConfiguration.getDatasource();
        if (datasource == null) {
            throw new RuntimeException("db source is not find, you need application input db.datasource");
        }
        Map<Object, Object> targetDataSources = new HashMap<>();
        // 使用自定义数据源列表
        List<String> keys = new ArrayList<>();
        datasource.forEach(dataSourceConfigProxy -> {
            DataSource dataSource = dataSourceCreate(dataSourceConfigProxy);
            String alias = dataSourceConfigProxy.getAlias();
            keys.add(alias);
            targetDataSources.put(alias, dataSource);
        });
        // 如果遍历完了. 还是这样. 那就有问题. 说明没有配资源
        if (targetDataSources.size() == 0) {
            throw new RuntimeException("db source is not find");
        }
        // 添加主库源
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        String masterKey = mSourceConfiguration.getPrimary();
        DynamicDataSourceContextHolder.DEFAULT_DATA_SOURCE = masterKey;
        DynamicDataSourceContextHolder.DATA_SOURCE_KEYS = keys;
        DynamicDataSourceContextHolder.setDefaultDataSource();
        dynamicDataSource.setDefaultTargetDataSource(targetDataSources.get(masterKey)); // 默认使用主库源
        dynamicDataSource.setTargetDataSources(targetDataSources);
        return dynamicDataSource;
    }


    @Bean
    public PlatformTransactionManager transactionManager(DynamicDataSource dynamicDataSource) {
        return new DataSourceTransactionManager(dynamicDataSource);
    }

    @Bean
    public SqlSessionFactory sqlSessionFactory(DynamicDataSource dynamicDataSource) throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dynamicDataSource);
        sessionFactory.setMapperLocations(((ResourcePatternResolver) new PathMatchingResourcePatternResolver())
                .getResources(this.mapperLocation));
        return sessionFactory.getObject();
    }
}